package com.leesche.netdoll.communication;

import java.nio.ByteOrder;

import com.leesche.netdoll.communication.protocol.MessageUtil;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;

public class DoubleHeaderLengthFieldBaseFrameDecoder extends LengthFieldBasedFrameDecoder {

	public DoubleHeaderLengthFieldBaseFrameDecoder(ByteOrder byteOrder, int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip,
			boolean failFast) {
		super(byteOrder, maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip, failFast);
	}

	@Override
	protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {

		int legalIndex = skipIllegalBytes(in);

		return legalIndex >= 0 ? super.decode(ctx, in) : null;
	}

	private static int skipIllegalBytes(ByteBuf in) {

		int begin = -1;

		for (int i = in.readerIndex(); i < in.writerIndex(); i++) {

			if (in.getByte(i) == 0x7e && (i + 5) < in.writerIndex() && in.getByte(i + 3) == 0x7e) {

				byte hrd1 = in.getByte(i);
				byte hrd2 = in.getByte(i + 1);
				byte hrd3 = in.getByte(i + 2);
				byte hrd4 = in.getByte(i + 3);
				byte hrd5 = in.getByte(i + 4);
				byte checksum = in.getByte(i + 5);

				if (assertChecksum(new byte[] { hrd1, hrd2, hrd3, hrd4, hrd5 }, checksum)) {
					begin = i;
					break;
				}

			}
		}

		if (begin > 0) {
			in.skipBytes(begin);
		}

		return begin;
	}

	private static boolean assertChecksum(byte[] hrd, byte expected) {

		byte checksum = MessageUtil.crc8(hrd);

		return checksum == expected;
	}

}
